var Gates = {
    'NAND': function(a,b) { 
        if(a === false || b === false) {
            return true;
        }
        return false;
    },

    NOT: function(a){ return this.NAND(a,a); },
    AND: function(a,b){ return this.NOT( this.NAND(a,b)); },
    OR: function(a,b) { return this.NAND( this.NOT(a), this.NOT(b)); },
    NOR: function(a,b){ return this.NOT(this.OR(a,b)); },
    XOR: function(a,b){ return this.AND( this.OR(a,b), this.NAND(a,b) );},
    NXOR: function(a,b) { return this.NOT( this.XOR(a,b) ); },
    MUX: function(a,b,sel) { return (sel) ? b : a; },
    DMUX: function(sel, input) { return (sel) ? [false,input] : [input, false];},
    MUX4Way: function(a,b,c,d, sel){
        
        if( !sel[0] && !sel[1] ){ 
            return a;
        }

        if( !sel[0] && sel[1] ) {
            return b;
        }

        if( sel[0] && !sel[1] ) {
            return c;
        }

        if( sel[0] && sel[1] ) {
            return d;
        }
    },

    MUX8Way: function(a,b,c,d,e,f,g,h, sel){
        if( !sel[0] && !sel[1] && !sel[2]){
            return a;
        }

        if( !sel[0] && !sel[1] && sel[2]){
            return b;
        }

        if( !sel[0] && sel[1] && !sel[2]){
            return c;
        }

        if( !sel[0] && sel[1] && sel[2]){
            return d;
        }

        if( sel[0] && !sel[1] && !sel[2]){
            return e;
        }

        if( sel[0] && !sel[1] && sel[2]){
            return f;
        }

        if( sel[0] && sel[1] && !sel[2]){
            return g;
        }

        if(sel[0] && sel[1] && sel[2]){
            return h;
        }

    },

    AbstractNOT: function(bits){
        var results = [];

        for(bit in bits){
            results.push(this.NOT(bit));
        }

        return results;
    },

    AbstractAND: function(a,b){
        var results = [];

        for( var i = 0; i < a.length ; i++ ){
            results[i] = this.AND(a[i], b[i]);
        }

        return results;
    },

    AbstractOR: function(a,b){
        var results = [];

        for( var i = 0; i < a.length ; i++ ){
            results[i] = this.OR(a[i], b[i]);
        }

        return results;  
    },

    AbstractORWay: function(bits){ return bits.reduce( this.OR ); },

    AbstractMUX: function(a,b, sel){
        return (sel) ? b : a; 
    }
};